package com.nanbei.a15;


import com.nanbei.a14.Target;
import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;
import org.aspectj.weaver.Advice;
import org.springframework.aop.aspectj.AspectJExpressionPointcut;
import org.springframework.aop.framework.ProxyFactory;
import org.springframework.aop.support.DefaultPointcutAdvisor;


/**
 * @ClassDescription: AOP
 * @JdkVersion: 1.8
 * @Author: libs
 * @Created: 2024/11/19 10:13
 */

public class A15 {
    public static void main(String[] args) {

        // 1.准备好切点
        AspectJExpressionPointcut pointcut = new AspectJExpressionPointcut();
        pointcut.setExpression("execution(* foo())");

        // 2.准备好通知  MethodInterceptor()是一个环绕通知
        MethodInterceptor advice = invocation -> {
            System.out.println("before...");
            Object proceed = invocation.proceed(); // 调用目标
            System.out.println("after...");
            return proceed;
        };

        // 3.备好切面
        DefaultPointcutAdvisor advisor = new DefaultPointcutAdvisor(pointcut,advice);

        /*
            4.创建代理
                a. proxyTargetClass = false 目标实现了接口，用JDK代理
                b. proxyTargetClass = false 目标没有实现接口，用Cglib代理
                b. proxyTargetClass = true  用Cglib代理
         */
        ProxyFactory proxyFactory = new ProxyFactory();
        Target1 target1 = new Target1();
        Target2 target2 = new Target2();
        proxyFactory.addAdvisor(advisor);
        proxyFactory.setTarget(target2);
        proxyFactory.setProxyTargetClass(true);
        proxyFactory.setInterfaces(target2.getClass().getInterfaces()); // 设置接口
        Target2 proxy = (Target2)proxyFactory.getProxy();
        System.out.println(proxy.getClass());
        proxy.foo();
        proxy.bar();


    }
    interface I1 {
        void foo();

        void bar();
    }

    static class Target1 implements I1 {
        public void foo() {
            System.out.println("target1 foo");
        }

        public void bar() {
            System.out.println("target1 bar");
        }

    }

    static class Target2 {
        public void foo() {
            System.out.println("target2 foo");
        }

        public void bar() {
            System.out.println("target2 bar");
        }
    }
}